home *** CD-ROM | disk | FTP | other *** search
- #import <stdio.h>
- #import <math.h>
- #import <strings.h>
- #import <stdlib.h>
- #import <streams/streams.h>
- #import <appkit/graphics.h>
- #import <appkit/NXBitmapImageRep.h>
- #import <appkit/color.h>
- #import "ppm.h"
- #import "NXBitmapImageRepControl.h"
- #import "ImageControl.h"
-
- @implementation PPM
-
- NXStream *myStream;
- unsigned char *data[5];
- char type[5];
- int width, height, levels;
- int bits;
- int cwid;
- int iwid;
- int padBits;
-
- - init
- {
- iwid = sizeof(int) * 8;
- cwid = sizeof(char) * 8;
-
- return self;
- }
-
- - free
- {
- return self;
- }
-
- - killToEOL
- {
- while (NXGetc(myStream) != '\n') ;
- return self;
- }
-
- - getString: (char *)str from: (NXStream *)stream
- {
- char buffer[256];
-
- do {
- NXScanf(stream, "%s", str);
- if (str[0] == '#') {
- NXScanf(stream, "%[^\n]", buffer); (void)NXGetc(stream);
- }
- } while (str[0] == '#');
-
- return self;
- }
-
- - (int)getIntFrom: (NXStream *)stream
- {
- char buffer[256];
-
- do {
- NXScanf(stream, "%s", buffer);
- if (buffer[0] == '#') {
- NXScanf(stream, "%[^\n]", buffer); (void)NXGetc(stream);
- }
- else break;
- } while (1);
- return(atoi(buffer));
- }
-
- - (BOOL)readRawFromStream
- {
- int x, y, shift, curInt;
- unsigned int c[3];
- unsigned int *dataII[3];
-
- dataII[0] = (unsigned int *)data[0];
- dataII[1] = (unsigned int *)data[1];
- dataII[2] = (unsigned int *)data[2];
-
- #ifdef DEBUG
- fprintf(stderr, "Okay, we're off and reading raw data\n");
- #endif
-
- [self killToEOL];
-
- shift = 0;
- dataII[0][curInt = 0] = 0;
- dataII[1][0] = 0;
- dataII[2][0] = 0;
- for (x = 0; x < height; x++) {
- for (y = 0; y < width; y++) {
- if (!shift) {
- dataII[0][curInt] = 0;
- dataII[1][curInt] = 0;
- dataII[2][curInt] = 0;
- }
- c[0] = [self getIntFrom: myStream];
- c[1] = [self getIntFrom: myStream];
- c[2] = [self getIntFrom: myStream];
- c[0] = c[0] << (iwid - bits);
- c[1] = c[1] << (iwid - bits);
- c[2] = c[2] << (iwid - bits);
- if (NXAtEOS(myStream)) return NO;
- if (shift + bits == iwid) {
- dataII[0][curInt] |= (c[0] >> shift);
- dataII[1][curInt] |= (c[1] >> shift);
- dataII[2][curInt] |= (c[2] >> shift);
- curInt++;
- shift = 0;
- }
- else if (shift + bits > iwid) {
- dataII[0][curInt] |= (c[0] >> shift);
- dataII[1][curInt] |= (c[1] >> shift);
- dataII[2][curInt++] |= (c[2] >> shift);
- shift = shift + bits - iwid;
- dataII[0][curInt] = c[0] << (bits - shift);
- dataII[1][curInt] = c[1] << (bits - shift);
- dataII[2][curInt] = c[2] << (bits - shift);
- }
- else {
- dataII[0][curInt] |= (c[0] >> shift);
- dataII[1][curInt] |= (c[1] >> shift);
- dataII[2][curInt] |= (c[2] >> shift);
- shift += bits;
- }
- }
- shift += padBits;
- }
-
- return YES;
- }
-
- - (BOOL)readCompressedFromStream
- {
- int x, y, shift, curByte;
- unsigned char c[3];
-
- #ifdef DEBUG
- fprintf(stderr, "Okay, we're off and reading condensed data\n");
- #endif
-
- [self killToEOL];
-
- shift = 0;
- data[0][curByte = 0] = 0;
- data[1][0] = 0;
- data[2][0] = 0;
- for (x = 0; x < height; x++) {
- for (y = 0; y < width; y++) {
- c[0] = NXGetc(myStream) << cwid - bits;
- c[1] = NXGetc(myStream) << cwid - bits;
- c[2] = NXGetc(myStream) << cwid - bits;
- if (NXAtEOS(myStream)) return NO;
- if (shift + bits == cwid) {
- data[0][curByte] |= (c[0] >> shift);
- data[1][curByte] |= (c[1] >> shift);
- data[2][curByte++] |= (c[2] >> shift);
- shift = 0;
- data[0][curByte] = 0;
- data[1][curByte] = 0;
- data[2][curByte] = 0;
- }
- else if (shift + bits > cwid) {
- data[0][curByte] |= (c[0] >> shift);
- data[1][curByte] |= (c[1] >> shift);
- data[2][curByte++] |= (c[2] >> shift);
- shift = shift + bits - cwid;
- data[0][curByte] = c[0] << (bits - shift);
- data[1][curByte] = c[1] << (bits - shift);
- data[2][curByte] = c[2] << (bits - shift);
- }
- else {
- data[0][curByte] |= (c[0] >> shift);
- data[1][curByte] |= (c[1] >> shift);
- data[2][curByte] |= (c[2] >> shift);
- shift += bits;
- }
- }
- shift += padBits;
- }
-
- return YES;
- }
-
- - readFromStream: (NXStream *)stream from: sender;
- {
- id image;
-
- #ifdef DEBUG
- fprintf(stderr, "Made it to read\n");
- #endif
-
- myStream = stream;
-
- [self getString: type from: myStream];
- #ifdef DEBUG
- fprintf(stderr, "Type: %s\n", type);
- #endif
- width = [self getIntFrom: myStream];
- height = [self getIntFrom: myStream];
- levels = [self getIntFrom: myStream];
- bits = log(levels + 1) / log (2);
- cwid = sizeof(unsigned char) * 8;
- iwid = sizeof(unsigned int) * 8;
- #ifdef DEBUG
- fprintf(stderr, "Type %s of dimensions %dx%d and levels %d or %d bits. intbits = %d, charbits = %d\n", type, width, height, levels + 1, bits, iwid, cwid);
- #endif
-
- image = [[NXBitmapImageRep alloc] initDataPlanes: NULL
- pixelsWide: width
- pixelsHigh: height
- bitsPerSample: bits
- samplesPerPixel: 3
- hasAlpha: NO
- isPlanar: YES
- colorSpace: NX_RGBColorSpace
- bytesPerRow: 0
- bitsPerPixel: 0];
- if (!image) return nil;
- [image getDataPlanes: data];
- #ifdef DEBUG
- fprintf(stderr, "%p %p %p\n", data[0], data[1], data[2]);
- #endif
-
- padBits = [image bytesPerRow] * 8 - bits * width;
-
- if (!strcmp(type, "P3")) {
- if (![self readRawFromStream]) {
- [image free];
- return nil;
- }
- }
- else if (!strcmp(type, "P6")) {
- if (![self readCompressedFromStream]) {
- [image free];
- return nil;
- }
- }
- else return nil;
-
- return image;
- }
-
- static BOOL WriteRaw(id image, NXStream *stream, id imageCon)
- {
- int w = [image pixelsWide],
- h = [image pixelsHigh],
- length = w * h;
- GetPixelNextFunc myFunc;
- Pixel *pixel;
- NXColorSpace cs = [image colorSpace];
- NXColor tColor;
- float maxColor = pow(2, (float)[image bitsPerSample]) - 1.0;
- int x, y;
-
- NXPrintf(stream, "P3\n");
- NXPrintf(stream, "%d %d\n", w, h);
- NXPrintf(stream, "%d\n", (int)maxColor);
- [imageCon resetNext];
- myFunc = [imageCon getNextFunction];
- for (x = y = 0; x < length; x++, y++) {
- pixel = myFunc();
- if (cs == NX_OneIsBlackColorSpace) {
- NXPrintf(stream, "%d ", 1 - pixel->values[0]);
- NXPrintf(stream, "%d ", 1 - pixel->values[0]);
- NXPrintf(stream, "%d ", 1 - pixel->values[0]);
- } else if (cs == NX_OneIsWhiteColorSpace) {
- NXPrintf(stream, "%d ", pixel->values[0]);
- NXPrintf(stream, "%d ", pixel->values[0]);
- NXPrintf(stream, "%d ", pixel->values[0]);
- } else if (cs == NX_RGBColorSpace) {
- NXPrintf(stream, "%d ", pixel->values[0]);
- NXPrintf(stream, "%d ", pixel->values[1]);
- NXPrintf(stream, "%d ", pixel->values[2]);
- } else if (cs == NX_CMYKColorSpace) {
- tColor = NXConvertCMYKToColor(
- (float)pixel->values[0] / maxColor,
- (float)pixel->values[1] / maxColor,
- (float)pixel->values[2] / maxColor,
- (float)pixel->values[3] / maxColor);
- NXPrintf(stream, "%d ", NXRedComponent(tColor) * maxColor);
- NXPrintf(stream, "%d ", NXGreenComponent(tColor) * maxColor);
- NXPrintf(stream, "%d ", NXBlueComponent(tColor) * maxColor);
- }
- if (y == 6) {
- y = 0;
- NXPrintf(stream, "\n");
- }
- }
-
- return YES;
- }
-
- static BOOL WriteCompact(id image, NXStream *stream, id imageCon)
- {
- int w = [image pixelsWide],
- h = [image pixelsHigh],
- length = w * h;
- GetPixelNextFunc myFunc;
- Pixel *pixel;
- NXColorSpace cs = [image colorSpace];
- NXColor tColor;
- float maxColor = pow(2, (float)[image bitsPerSample]) - 1.0;
- int x;
-
- NXPrintf(stream, "P6\n");
- NXPrintf(stream, "%d %d\n", w, h);
- NXPrintf(stream, "%d\n", (int)maxColor);
- [imageCon resetNext];
- myFunc = [imageCon getNextFunction];
- for (x = 0; x < length; x++) {
- pixel = myFunc();
- if (cs == NX_OneIsBlackColorSpace) {
- NXPutc(stream, 1 - pixel->values[0]);
- NXPutc(stream, 1 - pixel->values[0]);
- NXPutc(stream, 1 - pixel->values[0]);
- } else if (cs == NX_OneIsWhiteColorSpace) {
- NXPutc(stream, pixel->values[0]);
- NXPutc(stream, pixel->values[0]);
- NXPutc(stream, pixel->values[0]);
- } else if (cs == NX_RGBColorSpace) {
- NXPutc(stream, pixel->values[0]);
- NXPutc(stream, pixel->values[1]);
- NXPutc(stream, pixel->values[2]);
- // fprintf(stderr, "%3d %3d %3d...", pixel->values[0], pixel->values[1], pixel->values[2]);
- } else if (cs == NX_CMYKColorSpace) {
- tColor = NXConvertCMYKToColor(
- (float)pixel->values[0] / maxColor,
- (float)pixel->values[1] / maxColor,
- (float)pixel->values[2] / maxColor,
- (float)pixel->values[3] / maxColor);
- NXPutc(stream, NXRedComponent(tColor) * maxColor);
- NXPutc(stream, NXGreenComponent(tColor) * maxColor);
- NXPutc(stream, NXBlueComponent(tColor) * maxColor);
- }
- }
-
- return YES;
- }
-
- - (BOOL)write: (id)image toStream: (NXStream *)stream from: sender;
- {
- id imageCon = [sender getImageControl: image];
-
- if ([image bitsPerSample] > 8) {
- return WriteRaw(image, stream, imageCon);
- } else {
- return WriteCompact(image, stream, imageCon);
- }
- }
-
- - readAllFromStream: (NXStream *)stream from: sender
- {
- return nil;
- }
-
- - (BOOL)writeAll: (id)image toStream: (NXStream *)stream
- {
- return NO;
- }
-
- - customSaveView: (int)width
- {
- return nil;
- }
-
- - customOpenView: (int)width
- {
- return nil;
- }
-
- - (char *)getFormatName
- {
- return("Portable Pixmap (PPM)");
- }
-
- - (BOOL)setCustomParameter: (const char *)parameter withValue: (void *)ptr
- {
- return NO;
- }
-
- - (void *)getCustomParameter: (const char *)parameter
- {
- return nil;
- }
-
- - (char *)copyrightNotice
- {
- return "PPM Converter\nby Alex Raftis\nCopyright (c) 1991 Cal Poly State University\nEmail bugs to alex@data.ACS.CalPoly.EDU";
- }
-
- - (int)errorState
- {
- return CONVERT_ERR_NONE;
- }
-
- - (int)errorMessage
- {
- return ERROR_NO_ERROR;
- }
-
- - (char *)errorStringMessage
- {
- return NULL;
- }
-
- - (BOOL)needsWindowServer;
- {
- return NO;
- }
-
- - (char *)protocolVersion
- {
- return "1.0";
- }
-
- @end
-